package zero.tech.redis.lock;

import java.util.concurrent.TimeUnit;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class RedisLockUtil {
	@Autowired(required = false)
	private RedissonClient redissonClient;


	public static interface LockMethod<T> {
		public T lockRun() ;
	}

	public static interface LockMethodHasParam<T> {
		public T lockRun(Object... objs);
	}

	public <T> T tryLockMethod(LockMethod<T> method, String lockKey, int expireTime){
		T t=null;
		RLock lock=null;
		boolean res=false;
		try {
			lock=redissonClient.getLock(lockKey);
			res=lock.tryLock(expireTime, TimeUnit.SECONDS);
			if(res) {
				t = method.lockRun();
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally {
			if(lock!=null&&lock.isHeldByCurrentThread()&&lock.isLocked()) {
				lock.unlock();
			}
		}
		return t;
	}

	public <T> T tryLockMethod(LockMethodHasParam<T> method, String lockKey, int expireTime,
		Object... objs) {
		T t=null;
		RLock lock=null;
		boolean res=false;
		try {
			lock=redissonClient.getLock(lockKey);
			res=lock.tryLock(expireTime, TimeUnit.SECONDS);
			if(res) {
				t = method.lockRun(objs);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally {
			if(lock!=null&&lock.isHeldByCurrentThread()&&lock.isLocked()) {
				lock.unlock();
			}
		}
		return t;
	}



	public <T> T lockMethod(LockMethod<T> method, String lockKey, int leasetime){
		T t=null;
		RLock lock=null;
		try{
			lock=redissonClient.getLock(lockKey);
			lock.lock(leasetime,TimeUnit.SECONDS);
			t = method.lockRun();
		}catch (Exception e){
			throw e;
		}finally {
			if(lock!=null&&lock.isHeldByCurrentThread()&&lock.isLocked()) {
				lock.unlock();
			}
		}
		return t;
	}

}
